﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace server
{
    delegate void UpdateUserEventHandler(string name, User aUser,int flag);  //委托，此为重点
    class User
    {
        private Socket mSocket;
        public Thread thReceive;

        DateTime aliveTime;
        public UpdateUserEventHandler updateUser;
        bool loginStatus = false;

        Maticsoft.Model.RoleInfo mUserInfo = new Maticsoft.Model.RoleInfo();
        Maticsoft.DAL.RoleInfo mUserAction = new Maticsoft.DAL.RoleInfo();

        public Dictionary<string, Maticsoft.Model.Skill> skills = new Dictionary<string, Maticsoft.Model.Skill>();
        public Dictionary<string, baseskill> baseskills = new Dictionary<string, baseskill>();

        const int POINT2HP = 20;
        const int POINT2MP = 10;
        const int POINT2AT = 4;
        const int POINT2DE = 2;


        public User()
        {
            threadFlag = true;
        }

        public void setSocket(Socket socket)
        {
            this.mSocket = socket;

        }
        public Socket getSocket()
        {
            return this.mSocket;
        }

        //decode
        void decodeCmd(string cmd)
        {
            string[] arryCmd = cmd.Split('&');
            Dictionary<string,string>paras = new Dictionary<string,string>();
            for (int i = 1; i < arryCmd.Length;i++ )
            {
                string[] arryPara = arryCmd[i].Split('=');
                paras.Add(arryPara[0], arryPara[1]);
            }

            if (arryCmd[0] == "login")
            {
                if (loginStatus == false)
                {
                    if (verifyUser(paras["name"], paras["password"]) == true)
                    {
                        updateUser(this.mUserInfo.name, this, 0);
                        sendCmd("c01&f=0");
                        loginStatus = true;
                        aliveTime = DateTime.Now;
                    }
                    else
                    {
                        sendCmd("c01&f=1");
                        quitUser();
                    }
                }
                else
                {
                    //不处理
                }
            }

            if (arryCmd[0] == "first")
            {
                //昵称，性别，baseskill
                this.mUserInfo.nickName = paras["nickname"];
                this.mUserInfo.baseskill = paras["baseskill"];
                this.mUserInfo.sex = paras["sex"];
                this.mUserInfo.IsFirst = 1;
                if (this.mUserAction.Update(this.mUserInfo))
                {
                    sendCmd("c03&f=0");
                } 
                else
                {
                    sendCmd("c03&f=1");
                }              
                
            }

            if (arryCmd[0] == "UsePoint")
            {
                //昵称，性别，baseskill
                //this.mUserInfo.nickName = paras["nickname"];
                //this.mUserInfo.baseskill = paras["baseskill"];
                //this.mUserInfo.sex = paras["sex"];
                //this.mUserInfo.IsFirst = 1;
                //if (this.mUserAction.Update(this.mUserInfo))
                //{
                //    sendCmd("c03&f=0");
                //} 
                //else
                //{
                //    sendCmd("c03&f=1");
                //}              
                int addhp = 0;
                int addmp = 0;
                int addat = 0;
                int addde = 0;
                string skillName = "";
                bool validCmd = true;

                Maticsoft.Model.Skill learnSkill = new Maticsoft.Model.Skill();
                if (paras.ContainsKey("addhp"))
                {
                    addhp = int.Parse(paras["addhp"]);
                }
                if (paras.ContainsKey("addmp"))
                {
                    addmp = int.Parse(paras["addmp"]);
                }
                if (paras.ContainsKey("addat"))
                {
                    addat = int.Parse(paras["addat"]);
                }
                if (paras.ContainsKey("addde"))
                {
                    addde = int.Parse(paras["addde"]);
                }
                if (paras.ContainsKey("skillName"))
                {
                    skillName = paras["skillName"];
                    if (skills.ContainsKey(skillName))
                    {
                        learnSkill = skills[skillName];
                    }
                    else
                    {
                        validCmd = false;
                    }
                }

                
                if (mUserInfo.sypoint < (addde+addhp+addmp+addat+learnSkill.needPoint))
                {
                    validCmd = false;
                }
                else
                {
                    this.mUserInfo.hp = this.mUserInfo.hp + addhp * POINT2HP;
                    this.mUserInfo.mp = this.mUserInfo.mp + addmp * POINT2MP;
                    this.mUserInfo.de = this.mUserInfo.de + addde * POINT2AT;
                    this.mUserInfo.st = this.mUserInfo.st + addat * POINT2AT;
                    this.mUserInfo.skills = this.mUserInfo.skills + "&" + learnSkill.name;

                    this.mUserInfo.sypoint = this.mUserInfo.sypoint - addhp - addmp - addde - addat - learnSkill.needPoint;

                    this.mUserAction.Update(this.mUserInfo);

                    sendCmd("c07&f=1");
                }

                if (validCmd == false)
                {
                    sendCmd("c07&f=1");
                }

            }
            

            if (arryCmd[0] == "GBaseSkill")
            {
                //获得baseSkill
                string skillcmd;
                int number = 0;
                foreach (baseskill abaseSkill in baseskills.Values)
                {
                    skillcmd = "c05";
                    skillcmd = skillcmd + "&total=" + baseskills.Count;
                    number++;
                    skillcmd = skillcmd + "&number=" + number.ToString();
                    skillcmd = skillcmd + "&name=" + abaseSkill.getName();
                    skillcmd = skillcmd + "&desc=" + abaseSkill.getDesc();
                    sendCmd(skillcmd);
                }
            }


            if (arryCmd[0] == "GAllSkills")
            {
                //获得AllSkills
                string skillcmd;
                int number = 0;
                foreach (Maticsoft.Model.Skill aSkill in skills.Values)
                {
                    skillcmd = "c05";
                    skillcmd = skillcmd + "&total=" + skills.Count;
                    number++;
                    skillcmd = skillcmd + "&number=" + number.ToString();
                    skillcmd = skillcmd + "&name=" + aSkill.name;
                    skillcmd = skillcmd + "&curse_at=" + aSkill.curse_at;
                    skillcmd = skillcmd + "&curse_de=" + aSkill.curse_de;
                    skillcmd = skillcmd + "&damage=" + aSkill.damage;
                    skillcmd = skillcmd + "&damage_hot=" + aSkill.damage_hot;
                    skillcmd = skillcmd + "&damage_hot_time=" + aSkill.damage_hot_time;
                    skillcmd = skillcmd + "&damage_poison=" + aSkill.damage_poison;
                    skillcmd = skillcmd + "&desc=" + aSkill.desc;
                    skillcmd = skillcmd + "&hp_suck=" + aSkill.hp_suck;
                    skillcmd = skillcmd + "&mp=" + aSkill.mp;
                    skillcmd = skillcmd + "&mp_suck=" + aSkill.mp_suck;
                    sendCmd(skillcmd);
                }
            }

            if (arryCmd[0] == "GRoleInfo")
            {
                string roleInfocmd;
                roleInfocmd = "c06";
                roleInfocmd = roleInfocmd + "&name=" + this.mUserInfo.name;
                roleInfocmd = roleInfocmd + "&nickName=" + this.mUserInfo.nickName;
                roleInfocmd = roleInfocmd + "&baseskill=" + this.mUserInfo.baseskill;
                roleInfocmd = roleInfocmd + "&de=" + this.mUserInfo.de;
                roleInfocmd = roleInfocmd + "&hp=" + this.mUserInfo.hp;
                roleInfocmd = roleInfocmd + "&IsFirst=" + this.mUserInfo.IsFirst;
                roleInfocmd = roleInfocmd + "&mp=" + this.mUserInfo.mp;
                roleInfocmd = roleInfocmd + "&NowFailed=" + this.mUserInfo.NowFailed;
                roleInfocmd = roleInfocmd + "&NowVictory=" + this.mUserInfo.NowVictory;
                roleInfocmd = roleInfocmd + "&sex=" + this.mUserInfo.sex;
                roleInfocmd = roleInfocmd + "&skills=" + this.mUserInfo.skills;
                roleInfocmd = roleInfocmd + "&st=" + this.mUserInfo.st;
                roleInfocmd = roleInfocmd + "&sypoint=" + this.mUserInfo.sypoint;
                roleInfocmd = roleInfocmd + "&totalFailed=" + this.mUserInfo.totalFailed;
                roleInfocmd = roleInfocmd + "&totalpoint=" + this.mUserInfo.totalpoint;
                roleInfocmd = roleInfocmd + "&totalVictory=" + this.mUserInfo.totalVictory;
                sendCmd(roleInfocmd);
            }

            if (arryCmd[0] == "alive")
            {
                aliveTime = DateTime.Now;
            }

            if (arryCmd[0] == "register")
            {

                if (registerUser(paras["name"], paras["password"]) == true)
                {
                    //成功
                    sendCmd("c02&f=0");
                    quitUser();
                }
                else
                {
                    //失败
                    sendCmd("c02&f=1");
                    quitUser();
                }                
            }
            if (arryCmd[0] == "quit")
            {
                updateUser(this.mUserInfo.name, this, 1);
                quitUser();
            }
        }

        public bool checkAlive()
        {
            DateTime dt = DateTime.Now;
            TimeSpan t1 = new TimeSpan(dt.Ticks - aliveTime.Ticks);
            if (t1.Minutes > 0)
            {
                updateUser(this.mUserInfo.name, this, 1);
                quitUser();
                return false;
            }
            return true;
        }

        bool threadFlag;
        public void quitUser()
        {
            threadFlag = false;
            this.mSocket.Shutdown(SocketShutdown.Both);
            this.mSocket.Close();
        }
        bool registerUser(String name,String password)
        {
            bool ret;
            ret = this.mUserAction.Exists(name);
            if (ret == true)
            {
                return false;
            }

            this.mUserInfo.name = name;
            this.mUserInfo.password = password;
            this.mUserInfo.sex = "";
            this.mUserInfo.qq = "";
            this.mUserInfo.setupDate = DateTime.Now.ToString();
            this.mUserInfo.NowFailed = 0;
            this.mUserInfo.NowVictory = 0;
            this.mUserInfo.hp = 5;
            this.mUserInfo.mp = 5;
            this.mUserInfo.st = 5;
            this.mUserInfo.de = 5;
            this.mUserInfo.totalFailed = 0;
            this.mUserInfo.totalpoint = 30;
            this.mUserInfo.totalVictory = 0;
            this.mUserInfo.sypoint = 0;
            this.mUserInfo.baseskill = "";
            this.mUserInfo.IsFirst = 0;
            this.mUserInfo.isPaidUser = 0;
            this.mUserInfo.nickName = "";

            ret = this.mUserAction.Add(this.mUserInfo);

            return ret;
            //return msqlclient.regUser(name, password, sex, qq);
        }
        bool verifyUser(String name,String password)
        {

            this.mUserInfo = this.mUserAction.GetModel(name);
            if (this.mUserInfo == null)
            {
                return false;
            }
            else
            {
                if (password != this.mUserInfo.password)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }

        void sendCmd(String cmd)
        {
            cmd = cmd + "\r\n";
            Byte[] bySend = new byte[cmd.Length];
            //根据获取的长度定义一个Byte类型数组
            bySend = System.Text.Encoding.UTF8.GetBytes(cmd);
            mSocket.Send(bySend);
            return;
        }

        /// <summary>
        ///  接收客户端消息所使用的方法，带参数的线程委托必须使用object类型
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param> 

        // delegate void AddIfo_Invoke();
        public void Receive(object objConn)
        {

            //string[] stra = new string[20];
            //CheckForIllegalCrossThreadCalls = false;
            // 转换为Socket类型，与当前发送消息的客户端连接的Socket
            Socket socketConn = objConn as Socket;
            this.mSocket = socketConn;
            while (threadFlag)
            {
                if (socketConn.Available <= 0)
                {
                    Thread.Sleep(200);
                    continue;
                }
                //返回客户端终结点
                //string endpot;
                //endpot = socketConn.RemoteEndPoint.ToString();
                // 定义一个用来接收数据的缓存区,即一个2M的字节数组
                byte[] arrMsg = new byte[1024 * 2];
                // 接受消息并存入到arrMsg字节数组中，返回消息的长度
                int msgLen = socketConn.Receive(arrMsg);
                //转换为字符串
                string strMsg = System.Text.Encoding.Default.GetString(arrMsg, 0, msgLen);
                //添加至会话消息框
                decodeCmd(strMsg);

                //string a = "中文\r\n";
                //Byte[] bySend = new byte[a.Length];
                //////根据获取的长度定义一个Byte类型数组
                //bySend = System.Text.Encoding.UTF8.GetBytes(a);
                //socketConn.Send(bySend);


            }
            return;
        }
    }
}
